package ift605.tp2.sectionC.server;

import java.net.InetAddress;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.RemoteException;

import udes.ds.rmi.hw.BasicEquation;
import udes.ds.rmi.hw.Constant;
import udes.ds.rmi.hw.Equation;
import udes.ds.rmi.hw.MultiplicativeEquation;
import udes.ds.rmi.hw.PolynomialEquation;
import udes.ds.rmi.hw.UnknownEquationTypeException;

import ift605.tp2.sectionA.server.MyServer;
import ift605.tp2.sectionC.client.UnknownEquationUserInterface;

@SuppressWarnings("serial")
public class MyUnknownFailSafeServer extends MyServer implements MyUnknownFailSafeInterface{

	protected MyUnknownFailSafeServer() throws RemoteException {
		super();
	}

	public static void main(String[] args) {
		try {
			MyUnknownFailSafeServer server = new MyUnknownFailSafeServer();
			Naming.rebind("MyServer", server);

			try
			{
				System.out.println("IP Address : " + InetAddress.getLocalHost().getHostAddress());
			}
			catch( Exception e){}
		}
		catch (RemoteException e) {e.printStackTrace();}
		catch (MalformedURLException e) {e.printStackTrace();}
	}

	@Override
	public Equation resolveEquation(Equation aEquation,
			UnknownEquationUserInterface user) throws RemoteException,
			UnknownEquationTypeException {
		Equation answer = computeDerivative(aEquation, user);
		answer = cleanEquation(answer);
		return answer;
	}
	
	protected Equation computeDerivative(Equation aEquation,
			UnknownEquationUserInterface user) throws RemoteException {
		Equation result = new Constant(0);
		if(aEquation.getClass() == Constant.class)
		{
			//Return Constant(0), but it is by default
		}
		else if(aEquation.getClass() == BasicEquation.class)
		{
			BasicEquation casted = (BasicEquation)aEquation;
			if(casted.getExponent() != 1)
			{
				result = new BasicEquation( casted.getCoefficient() * casted.getExponent(), casted.getExponent() - 1);
			}
			else
			{
				result = new Constant( casted.getCoefficient() * casted.getExponent());
			}
		}
		else if(aEquation.getClass() == PolynomialEquation.class)
		{
			PolynomialEquation casted = (PolynomialEquation)aEquation;
			result = new PolynomialEquation( computeDerivative(casted.getFirst(), user) , computeDerivative(casted.getSecond(), user));
		}
		else if(aEquation.getClass() == MultiplicativeEquation.class)
		{
			MultiplicativeEquation casted = (MultiplicativeEquation)aEquation;
			result = new PolynomialEquation(  	new MultiplicativeEquation( casted.getFirst() , computeDerivative(casted.getSecond(), user)), 
												new MultiplicativeEquation( computeDerivative(casted.getFirst(), user) , casted.getSecond()));
		}
		else
		{
			result = user.resolveUnknownEquation(aEquation);
		}
		return result;
	}

}
